package com.baijiayun.liveuibase.devicetesting.fragment

import android.media.AudioFormat
import android.media.AudioRecord
import android.media.MediaRecorder
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.baijiayun.livecore.utils.LPRxUtils
import com.baijiayun.liveuibase.R
import com.baijiayun.liveuibase.devicetesting.DeviceTestingViewModel
import com.baijiayun.liveuibase.utils.DisplayUtils
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.bjy_base_fragment_device_testing_mic.*
import kotlinx.android.synthetic.main.bjy_base_fragment_device_testing_speaker.*
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
import kotlin.math.log10


class DeviceTestingMicFragment : Fragment() {
    private var disposableOfTime: Disposable? = null
    private lateinit var viewModel: DeviceTestingViewModel
    private var volumeBlockNum = 0

    private val SAMPLE_RATE_IN_HZ = 8000
    private var bufferSize = 0
    private var audioRecord: AudioRecord? = null
    private var isRun = false
    private val mLock = Object()
    private var mHandler = Handler {
      when (it.what) {
          1 -> {
              updateMicVolumeView(it.obj as Int)
              true
          }
            else -> {
                true
            }
        }
    }
    private var recordThread: Thread? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.bjy_base_fragment_device_testing_mic, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProvider(requireActivity()).get(DeviceTestingViewModel::class.java)
        initView()
        initAction()
    }

    private fun initView() {
        initMicVolumeView()
        bjy_base_fragment_device_testing_mic_description_tv.visibility = View.GONE
        bjy_base_fragment_device_testing_mic_positive_btn.visibility = View.GONE
        bjy_base_fragment_device_testing_mic_negative_btn.visibility = View.GONE
        bjy_base_fragment_device_testing_mic_positive_btn.setOnClickListener {
            viewModel.micResult = true
            viewModel.setTestStep(DeviceTestingViewModel.TestStep.TestEnd)
        }
        bjy_base_fragment_device_testing_mic_negative_btn.setOnClickListener {
            val dialogFragment = DeviceTestingDialogFragment()
            dialogFragment.setTitle(getString(R.string.bjy_base_device_testing_mic_confirm_question))
            dialogFragment.setContent(getString(R.string.bjy_base_device_testing_mic_confirm_tip))
            dialogFragment.setNegativeButtonText(getString(R.string.bjy_base_device_testing_mic_no))
            dialogFragment.setPositiveButtonText(getString(R.string.bjy_base_device_testing_mic_yes))
            dialogFragment.setButtonClickedListener(object : DeviceTestingDialogFragment.OnButtonClickedListener {
                override fun onPositive() {
                    viewModel.micResult = true
                    viewModel.setTestStep(DeviceTestingViewModel.TestStep.TestEnd)
                    dialogFragment.dismissAllowingStateLoss()
                }

                override fun onNegative() {
                    viewModel.micResult = false
                    viewModel.setTestStep(DeviceTestingViewModel.TestStep.TestEnd)
                    dialogFragment.dismissAllowingStateLoss()
                }
            })
            dialogFragment.show(activity!!.supportFragmentManager, "mic")
        }
        LPRxUtils.dispose(disposableOfTime)
        disposableOfTime = Observable.timer(2, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe{
                    bjy_base_fragment_device_testing_mic_description_tv.visibility = View.VISIBLE
                    bjy_base_fragment_device_testing_mic_positive_btn.visibility = View.VISIBLE
                    bjy_base_fragment_device_testing_mic_negative_btn.visibility = View.VISIBLE
                    updateMicVolumeView(10)
                }
        recordThread= Thread {
            bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT)
            audioRecord = AudioRecord(MediaRecorder.AudioSource.MIC,
                SAMPLE_RATE_IN_HZ,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, bufferSize)
            audioRecord?.startRecording()
            isRun = true
            val buffer = ShortArray(bufferSize)
            while (isRun) {
                val r = audioRecord?.read(buffer, 0, bufferSize)
                var v = 0L
                for (i in buffer.indices) {
                    v += buffer[i] * buffer[i]
                }
                val mean = (v / r!!).toDouble()
                val volume = ((10 * log10(mean)).toInt() - 30) / 5
                val message = Message()
                message.what = 1
                message.obj = volume
                mHandler.sendMessage(message)
                synchronized(mLock) {
                    try {
                        mLock.wait(200)
                    } catch (e: InterruptedException) {
                        e.printStackTrace()
                    }
                }
            }
            audioRecord?.stop()
            audioRecord?.release()
            audioRecord = null
        }
        recordThread?.start()
    }

    private fun initAction() {
        viewModel.earphoneState.observe(this, {
            bjy_base_fragment_device_testing_mic_name_tv.text = if (it) getString(R.string.bjy_base_device_testing_mic_other) else getString(R.string.bjy_base_device_testing_mic_default)
        })
    }

    private fun initMicVolumeView() {
        bjy_base_fragment_device_testing_mic_volume_container.post {
            val containerWidth = bjy_base_fragment_device_testing_mic_volume_container.width
            volumeBlockNum = containerWidth / DisplayUtils.dip2px(context!!, 12f)
            for (i in 0 until volumeBlockNum) {
                val view = View(context)
                view.background = ContextCompat.getDrawable(context!!, R.drawable.bjy_base_fragment_device_testing_bg_volume_normal)
                val layoutParams = LinearLayout.LayoutParams(DisplayUtils.dip2px(context!!, 8f), LinearLayout.LayoutParams.MATCH_PARENT)
                layoutParams.marginEnd = DisplayUtils.dip2px(context!!, 4f)
                view.layoutParams = layoutParams
                bjy_base_fragment_device_testing_mic_volume_container.addView(view, i)
            }
        }
    }

    private fun updateMicVolumeView(enableNum: Int) {
        if (volumeBlockNum == 0) return
        for (i in 0 until volumeBlockNum) {
            if (i < enableNum) {
                bjy_base_fragment_device_testing_mic_volume_container?.getChildAt(i)?.background = ContextCompat.getDrawable(context!!, R.drawable.bjy_base_fragment_device_testing_bg_volume_enable)
            } else {
                bjy_base_fragment_device_testing_mic_volume_container?.getChildAt(i)?.background = ContextCompat.getDrawable(context!!, R.drawable.bjy_base_fragment_device_testing_bg_volume_normal)
            }
        }
    }

    override fun onPause() {
        super.onPause()
        LPRxUtils.dispose(disposableOfTime)
        isRun = false
    }
}